package net.lookyou.boot.demo.config.redis;

import cn.hutool.core.collection.CollectionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
import org.springframework.session.data.redis.RedisIndexedSessionRepository;
import org.springframework.session.events.SessionDestroyedEvent;

import java.util.Map;

/**
 * SpringSession集成底层Redis实现，如果底层分布式会话保持方式不是基于Redis,则该类无法正常使用
 *
 * hasLogin:通过传递登录账号，判断该账号是否已经登录过，该方法是一个业务的延伸，比如我们对当前账号判断是否已经登录过，如果登录则提示需要退出才能继续登录的操作等
 * loadByAccount:根据登录账号获取当前已经登录的Session会话Map集合
 * destroySession:根据登录账号销毁当前所有该账号的Session会话信息，此接口和产品经理要求的踢人下线操作一致
 */
public class RedisSessionService implements SessionService {

    Logger logger= LoggerFactory.getLogger(RedisSessionService.class);
    final RedisIndexedSessionRepository redisIndexedSessionRepository;
    final ApplicationEventPublisher applicationEventPublisher;
    public RedisSessionService(RedisIndexedSessionRepository redisIndexedSessionRepository, ApplicationEventPublisher applicationEventPublisher) {
        this.redisIndexedSessionRepository = redisIndexedSessionRepository;
        this.applicationEventPublisher = applicationEventPublisher;
    }
    @Override
    public boolean hasLogin(String account) {
        return CollectionUtil.isNotEmpty(loadByAccount(account));
    }
    @Override
    public Map<String, ? extends Session> loadByAccount(String account) {
        logger.info("收集当前登录会话session，账号:{}",account);
        return redisIndexedSessionRepository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,account);
    }
    @Override
    public void destroySession(String account) {
        logger.info("销毁当前登录session会话,账号：{}",account);
        Map<String,? extends Session> sessionMap=loadByAccount(account);
        if (CollectionUtil.isNotEmpty(sessionMap)){
            logger.info("当前登录会话size:{}",sessionMap.size());
            for (Map.Entry<String,? extends Session> sessionEntry:sessionMap.entrySet()){
                String key=sessionEntry.getKey();
                Session session=sessionEntry.getValue();
                logger.info("destroy session key:{}",key);
                //删除
                redisIndexedSessionRepository.deleteById(session.getId());
                //广播Session会话销毁事件
                applicationEventPublisher.publishEvent(new SessionDestroyedEvent(redisIndexedSessionRepository,session));
            }
        }
    }

}